package com.dom.invoapp.modular.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dom.common.constants.Constants;
import com.dom.common.enums.CancelStatEnum;
import com.dom.common.enums.SaleOrderStatEnum;
import com.dom.common.enums.VerfyStatEnum;
import com.dom.common.exception.ServiceException;
import com.dom.common.model.standard.ResponseModel;
import com.dom.common.model.vo.sale.*;
import com.dom.invoapp.dao.entity.TClientInfo;
import com.dom.invoapp.dao.entity.TmMarketSaleDetailFlow;
import com.dom.invoapp.dao.entity.TmMarketSaleFlow;
import com.dom.invoapp.dao.service.ITClientInfoService;
import com.dom.invoapp.dao.service.ITTradeDateService;
import com.dom.invoapp.dao.service.ITmMarketSaleDetailFlowService;
import com.dom.invoapp.dao.service.ITmMarketSaleFlowService;
import com.dom.invoapp.util.ComputeUtil;
import com.xiaoleilu.hutool.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MarketSaleService {

    @Autowired
    private ITmMarketSaleDetailFlowService marketSaleDetailFlowService;
    @Autowired
    private ITmMarketSaleFlowService marketSaleFlowService;
    @Autowired
    private ITTradeDateService tradeDateService;
    @Autowired
    private ITClientInfoService clientInfoService;

    public String insertMarketSale(M030R request) {
        TmMarketSaleFlow flow = new TmMarketSaleFlow();
        flow.setMemCode(0);
//        TODO 部分数据初始化
//        flow.setMemCode(request.getMemCode());
        flow.setSaleType(request.getSaleType());
        flow.setCustCode(request.getCustCode() == null ? null : Integer.valueOf(request.getCustCode()));
        flow.setSourBillId(request.getSourBillId());
        flow.setSourBillType(request.getSourBillType() == null ? null : Integer.valueOf(request.getSourBillType()));
        flow.setOrganCode(request.getOrgId());
        flow.setDocuMakerId(1111);
//        flow.setDocuMakerId(request.getOperId());
        flow.setExchDate(tradeDateService.getExchDate(0));
        flow.setDigest(request.getBillAbstract());
        flow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        flow.setVerfyStat(VerfyStatEnum.VERFY_STAT_CONFIRMING.getCode());
        flow.setCancelStat(CancelStatEnum.CANCEL_STAT_NORMAL.getCode());
        flow.setVersion(0);
        boolean isTrue = marketSaleFlowService.insert(flow);
        if(!isTrue){
            log.info("登记销售单失败, result:{}", isTrue);
            throw new ServiceException("9001", "录入销售订单数据库异常");
        }
        List<TmMarketSaleDetailFlow> list = new ArrayList<TmMarketSaleDetailFlow>();
        request.getSaleDetailData().forEach(saleDetailInfo -> {
            list.add(convertEntity(saleDetailInfo,flow));
        });
        boolean batchResult = marketSaleDetailFlowService.insertBatch(list);
        if(!batchResult){
            log.info("录入销售单明细失败, result:{}", batchResult);
            throw new ServiceException("9001", "录入销售单明细数据库异常");
        }
        return flow.getId().toString();
    }


    public Map<String,Object> getAllClientInfoToMap(){
        Wrapper<TClientInfo> wrapper = new EntityWrapper<TClientInfo>();
        List<TClientInfo> list = clientInfoService.selectList(wrapper);
        Map<String,Object> map = new HashMap<String,Object>();
        for (TClientInfo info: list ) {
            map.put(info.getCustCode().toString(),info.getAbbrName());
        }
        return map;
    }

    private TmMarketSaleDetailFlow convertEntity(SaleDetailInfo info, TmMarketSaleFlow flow) {
        TmMarketSaleDetailFlow detail = new TmMarketSaleDetailFlow();
        detail.setMemCode(flow.getMemCode());
        detail.setSaleId(flow.getId().toString());
        detail.setGoodCode(StringUtils.isEmpty(info.getGoodCode()) ? null : Integer.valueOf(info.getGoodCode()));
        detail.setGoodName(info.getGoodName());
        detail.setVarietyCode(StringUtils.isEmpty(info.getVarietyCode()) ? null : Integer.valueOf(info.getVarietyCode()));
        detail.setVarietyName(info.getVarietyName());
        detail.setStandardName(info.getStandardName());
        detail.setUnit(info.getUnit());
        detail.setOutTaxRate(StringUtils.isEmpty(info.getOutTaxRate()) ? BigDecimal.ZERO : new BigDecimal(info.getOutTaxRate()));
        detail.setPrice(StringUtils.isEmpty(info.getPrice()) ? BigDecimal.ZERO : new BigDecimal(info.getPrice()));
        detail.setNoTaxPrice(ComputeUtil.computeNoTaxPrice(info.getPrice(),info.getOutTaxRate()));
        detail.setAmount(StringUtils.isEmpty(info.getAmount()) ? BigDecimal.ZERO : new BigDecimal(info.getAmount()));
        detail.setRemAmount(StringUtils.isEmpty(info.getRemAmount()) ? BigDecimal.ZERO : new BigDecimal(info.getRemAmount()));
        detail.setBal(ComputeUtil.computeGoodsBal(info.getPrice(),info.getAmount()));
        detail.setNoTaxBal(ComputeUtil.computeGoodsNoTaxBal(info.getPrice(),info.getAmount(),info.getOutTaxRate()));
        detail.setEstOutTax(ComputeUtil.computeEstOutTax(info.getPrice(),info.getOutTaxRate(),info.getAmount()));
        detail.setDigest(info.getBillAbstract());
        detail.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        detail.setVersion(0);
        return detail;
    }

    public Page<TmMarketSaleFlow> getMarketSaleList(M039R request) {
        Page<TmMarketSaleFlow> page = new Page<TmMarketSaleFlow>();
        page.setSize(request.getPs() == 0 ? 20 : request.getPs());
        page.setCurrent(request.getPn());

        Wrapper wrapper = new EntityWrapper();
        if (!StringUtils.isEmpty(request.getCustCode())) {
            wrapper.and().eq("cust_code",request.getCustCode());
        }
        if (!StringUtils.isEmpty(request.getSourBillType())) {
            wrapper.and().eq("sour_bill_type",request.getSourBillType());
        }
        if (!StringUtils.isEmpty(request.getSaleType())) {
            wrapper.and().eq("sale_type",request.getSaleType());
        }
        if (!StringUtils.isEmpty(request.getMakerId())) {
            wrapper.and().eq("docu_maker_id",request.getMakerId());
        }
        if(StringUtils.isNotEmpty(request.getExchStartDate()) && StringUtils.isNotEmpty(request.getExchEndDate())){
            wrapper.between("exch_date", DateUtil.parse(request.getExchStartDate(), "yyyy-MM-dd"), DateUtil.parse(request.getExchEndDate(), "yyyy-MM-dd"));
        }
//        if (StringUtils.isNotEmpty(request.getSaleEndDate()) && StringUtils.isNotEmpty(request.getSaleEndDate())){
//            wrapper.and().between("make_date", DateUtil.parse(request.getSaleStartDate(), "yyyy-MM-dd"), DateUtil.parse(request.getSaleEndDate(), "yyyy-MM-dd"));
//        }
        if(StringUtils.isNotEmpty(request.getId())){
            wrapper.and().eq("id",request.getId());
        }
        List<String> saleList = new ArrayList<>();
        saleList.add("exch_date");
        saleList.add("make_date");
        wrapper.and().notIn("cancel_stat", CancelStatEnum.CANCEL_STAT_CANCELED.getCode());
        wrapper.orderBy(true, saleList, false);
        return marketSaleFlowService.selectPage(page,wrapper);
    }

    public M033A findUpdateMarketSale(String id) {
        M039R request = new M039R();
        request.setId(id);
        Page<TmMarketSaleFlow> page = getMarketSaleList(request);
        Map<String,Object> map = getAllClientInfoToMap();
        M033A result = toMarketSale((TmMarketSaleFlow)page.getRecords().get(0),map);
        Wrapper<TmMarketSaleDetailFlow> wrapper = new EntityWrapper();
        wrapper.eq("sale_id",id);
        List<TmMarketSaleDetailFlow> list = marketSaleDetailFlowService.selectList(wrapper);
        List<SaleDetailInfo> detailList = new ArrayList<SaleDetailInfo>();
        for (TmMarketSaleDetailFlow flow:list) {
            SaleDetailInfo info = toMarketSaleDetail(flow);
            detailList.add(info);
        }
        result.setSaleDetailData(detailList);
        return result;
    }

    private SaleDetailInfo toMarketSaleDetail(TmMarketSaleDetailFlow flow) {
        SaleDetailInfo info = new SaleDetailInfo();
        info.setKeyId(flow.getId().toString());
        info.setAmount(flow.getAmount() == null ? null : flow.getAmount().toString());
        info.setBal(flow.getBal() == null ? null : flow.getBal().toString());
        info.setBillAbstract(flow.getDigest());
        info.setEstOutTax(flow.getEstOutTax() == null ? null : flow.getEstOutTax().toString());
        info.setGoodCode(flow.getGoodCode() == null ? null : flow.getGoodCode().toString());
        info.setGoodName(flow.getGoodName());
//        info.setSource(flow.get);
//        info.setNoAmount(flow.getFamount());
        info.setNoTaxBal(flow.getNoTaxBal() == null ? null : flow.getNoTaxBal().toString());
        info.setNoTaxPrice(flow.getNoTaxPrice() == null ? null : flow.getNoTaxPrice().toString());
        info.setOutTaxRate(flow.getOutTaxRate() == null ? null : flow.getOutTaxRate().toString());
        info.setPrice(flow.getPrice() == null ? null : flow.getPrice().toString());
        info.setRemAmount(flow.getRemAmount() == null ? null : flow.getRemAmount().toString());
        info.setStandardName(flow.getStandardName());
        info.setStat(Integer.toString(flow.getStat()));
        info.setUnit(flow.getUnit());
        info.setVarietyCode(flow.getVarietyCode() == null ? null : flow.getVarietyCode().toString());
        info.setVarietyName(flow.getVarietyName());
        return info;
    }

    private M033A toMarketSale(TmMarketSaleFlow flow,Map<String,Object> map) {
        M033A result = new M033A();
        result.setId(flow.getId().toString());
        result.setBillAbstract(flow.getDigest());
        result.setSaleType(flow.getSaleType());
        result.setSourBillType(flow.getSourBillType() == null ? null : flow.getSourBillType().toString());
        result.setSourBillId(flow.getSourBillId());
        result.setCancelStat(Integer.toString(flow.getCancelStat()));
        result.setCancelTime(flow.getCancelTime() == null ? null : DateUtil.format(flow.getCancelTime(), Constants.DATE_FORMAT_YYYY_MM_DD));
        result.setBillAbstract(flow.getDigest());
        result.setCancelStat(Integer.toString(flow.getCancelStat()));
        result.setCancelTime(flow.getCancelTime() == null ? "" : DateUtil.formatDate(flow.getCancelTime()));
        result.setCompCode(flow.getOrganCode() == null ? "" : flow.getOrganCode().toString());
        result.setCustCode(flow.getCustCode() == null ? "" : flow.getCustCode().toString());
        result.setCustName(map.get(flow.getCustCode().toString()).toString());
//        result.setSaleDate(flow.get);
        result.setExchDate(flow.getExchDate() == null ? "" : DateUtil.formatDate(flow.getExchDate()));
//        result.setLinkMan(flow.getContName());
//        result.setLinkManTel(flow.getContPhone());
        result.setMakeDate(flow.getMakeDate() == null ? "" : DateUtil.formatDate(flow.getMakeDate()));
        result.setMakerId(flow.getDocuMakerId() == null ? "" : flow.getDocuMakerId().toString());
        result.setStat(Integer.toString(flow.getStat()));
        result.setVerfierId(flow.getVerfierId());
        result.setVerfyDate(flow.getVerfyDate() == null ? "" : DateUtil.formatDate(flow.getVerfyDate()));
        result.setVerfyErrMsg(flow.getVerfyErrMsg());
        result.setVerfyStat(Integer.toString(flow.getVerfyStat()));
        result.setCancelStat(Integer.toString(flow.getCancelStat()));
        return result;
    }

    public boolean marketSaleDel(String id) {
        Wrapper<TmMarketSaleFlow> wrapper = new EntityWrapper();
        TmMarketSaleFlow flow = new TmMarketSaleFlow();
        flow.setCancelStat(CancelStatEnum.CANCEL_STAT_CANCELED.getCode());
        wrapper.eq("id",id);
        return marketSaleFlowService.update(flow,wrapper);
    }

    public ResponseModel marketSaleModify(M032R request) {
        TmMarketSaleFlow flow = new TmMarketSaleFlow();
        flow.setId(StringUtils.isEmpty(request.getId()) ? null : Integer.valueOf(request.getId()));
        flow.setCustCode(StringUtils.isEmpty(request.getCustCode()) ? null : Integer.valueOf(request.getCustCode()));
//        flow.setAbbrName(request.getCustName());
        flow.setSaleType(request.getSaleType());
        flow.setSourBillType(StringUtils.isEmpty(request.getSourBillType()) ? null : Integer.valueOf(request.getSourBillType()) );
        flow.setSourBillId(request.getSourBillId());
//        flow.setContName(request.getLinkMan());
//        flow.setContPhone(request.getLinkManTel());
//        flow.setSaleDate(StringUtils.isEmpty(request.getSaleDate()) ? null : DateUtil.parseDate(request.getDeliDate()));
//        flow.setAddress(request.getAddress());
        flow.setDigest(request.getBillAbstract());
        Wrapper<TmMarketSaleFlow> wrapper = new EntityWrapper();
        wrapper.eq("id",request.getId());
        boolean isTrue = marketSaleFlowService.update(flow,wrapper);
        if(!isTrue){
            throw new ServiceException("8001", "修改销售单数据库异常");
        }
        updateMarketSaleDetail(request);
        return new ResponseModel("RSP000000","销售单数据修改完成！");
    }

    private void updateMarketSaleDetail(M032R request) {
        TmMarketSaleDetailFlow detail = new TmMarketSaleDetailFlow();
        List<String> list = new ArrayList<String>();
        Wrapper<TmMarketSaleDetailFlow> wap = new EntityWrapper();

        if(request.getSaleDetailData() != null || request.getSaleDetailData().size() != 0){
            for (M042R m:request.getSaleDetailData()) {
                if (StringUtils.isNotEmpty(m.getKeyId())){
                    list.add(m.getKeyId());
                }
            }
        }
        wap.notIn("id",list);
        marketSaleDetailFlowService.delete(wap);
        List<String> strings = marketSaleDetailFlowService.selectDetailIdBySaleId(request.getId());
        for (M042R m:request.getSaleDetailData()) {
            TmMarketSaleDetailFlow detailFlow = toDetailFlow(m,request);
            if (!StringUtils.isEmpty(m.getKeyId()) &&
                    strings.contains(m.getKeyId())) {
                Wrapper<TmMarketSaleDetailFlow> wrapper = new EntityWrapper();
                wrapper.eq("id",m.getKeyId());
                marketSaleDetailFlowService.update(detailFlow,wrapper);
            }else{
                marketSaleDetailFlowService.insert(detailFlow);
            }
        }
    }

    private TmMarketSaleDetailFlow toDetailFlow(M042R detail,M032R request){
        TmMarketSaleDetailFlow detailFlow = new TmMarketSaleDetailFlow();
        detailFlow.setRemAmount(detail.getRemAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getRemAmount()));
//        detailFlow.setFamount(detail.getNoAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getNoAmount()));
        detailFlow.setAmount(detail.getAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getAmount()));
        detailFlow.setVersion(0);
        detailFlow.setId(StringUtils.isEmpty(detail.getKeyId()) ? null : Integer.valueOf(detail.getKeyId()));
        detailFlow.setSaleId(request.getId());
        detailFlow.setVarietyName(detail.getVarietyName());
        detailFlow.setVarietyCode(detail.getVarietyCode() == null ? null : Integer.valueOf(detail.getVarietyCode()));
        detailFlow.setUnit(detail.getUnit());
        detailFlow.setStandardName(detail.getStandardName());
//        detailFlow.setSource(detail.getSource());
        detailFlow.setPrice(detail.getPrice() == null ? BigDecimal.ZERO : new BigDecimal(detail.getPrice()));
        detailFlow.setOutTaxRate(detail.getOutTaxRate() == null ? BigDecimal.ZERO : new BigDecimal(detail.getOutTaxRate()));
        detailFlow.setNoTaxBal(ComputeUtil.computeGoodsNoTaxBal(detail.getPrice(),detail.getAmount(),detail.getOutTaxRate()));
        detailFlow.setNoTaxPrice(ComputeUtil.computeNoTaxPrice(detail.getPrice(),detail.getOutTaxRate()));
//        detailFlow.setMemCode(request.getMemCode());
        detailFlow.setMemCode(0);
        detailFlow.setGoodName(detail.getGoodName());
        detailFlow.setGoodCode(detail.getGoodCode() == null ? null : Integer.valueOf(detail.getGoodCode()));
        detailFlow.setEstOutTax(ComputeUtil.computeEstOutTax(detail.getPrice(),detail.getOutTaxRate(),detail.getAmount()));
        detailFlow.setDigest(detail.getBillAbstract());
        detailFlow.setBal(ComputeUtil.computeGoodsBal(detail.getPrice(),detail.getAmount()));
        detailFlow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        return detailFlow;
    }
    private TmMarketSaleFlow toMarketSale(M032R request){
        TmMarketSaleFlow flow = new TmMarketSaleFlow();
        flow.setMemCode(request.getMemCode());
//        TODO 部分数据赋值
//        flow.setMemCode(request.getMemCode());
        flow.setSaleType(request.getSaleType());
        flow.setCustCode(request.getCustCode() == null ? null : Integer.valueOf(request.getCustCode()));
        flow.setSourBillId(request.getSourBillId());
        flow.setSourBillType(request.getSourBillType() == null ? null : Integer.valueOf(request.getSourBillType()));
        flow.setOrganCode(request.getOrgId());
        flow.setDocuMakerId(1111);
//        flow.setDocuMakerId(request.getOperId());
        flow.setExchDate(tradeDateService.getExchDate(0));
        flow.setDigest(request.getBillAbstract());
        flow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        flow.setVerfyStat(VerfyStatEnum.VERFY_STAT_CONFIRMING.getCode());
        flow.setCancelStat(CancelStatEnum.CANCEL_STAT_NORMAL.getCode());
        return flow;
    }
}
